package com.fin.zw.intelligentbot.controller.api;

import com.alibaba.fastjson.JSONObject;
import com.fin.zw.intelligentbot.annotation.CurrentUser;
import com.fin.zw.intelligentbot.entity.*;
import com.fin.zw.intelligentbot.enums.Sex;
import com.fin.zw.intelligentbot.enums.SourceType;
import com.fin.zw.intelligentbot.enums.TaskStatus;
import com.fin.zw.intelligentbot.model.base.Customer;
import com.fin.zw.intelligentbot.model.base.Robot;
import com.fin.zw.intelligentbot.model.base.Scene;
import com.fin.zw.intelligentbot.model.interactive.VariablesApiRq;
import com.fin.zw.intelligentbot.model.request.CallDetailRecord;
import com.fin.zw.intelligentbot.model.request.DialLogRequest;
import com.fin.zw.intelligentbot.model.response.DialLogResponse;
import com.fin.zw.intelligentbot.model.response.TaskLogResponse;
import com.fin.zw.intelligentbot.model.session.SessionModel;
import com.fin.zw.intelligentbot.repository.*;
import com.fin.zw.intelligentbot.service.CommonService;
import com.fin.zw.intelligentbot.service.DialLogService;
import com.fin.zw.intelligentbot.service.UploadFileService;
import com.fin.zw.intelligentbot.util.Base64Utils;
import com.fin.zw.intelligentbot.util.FileUtil;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@RestController
@RequestMapping("/cdr")
@Api(value = "日志的处理",description = "日志的处理")
public class DialLogController {

    private static final Logger log = LoggerFactory.getLogger(DialLogController.class);

    @Autowired
    private TaskCustomerRepository taskCustomerRepository;

    @Autowired
    private UploadFileRepository uploadFileRepository;

    @Autowired
    private UploadFileService uploadFileService;

    @Autowired
    private RobotInfoRepository   robotService;

    @Autowired
    private DialLogService dialLogService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private CompanyRepository companyRepository;

    @Autowired
    private SceneInfoRepository sceneInfoRepository;

    @Autowired
    private CategoryLabelRepository categoryLabelRepository;


    @PostMapping("/add")
    @ApiOperation(value = "呼叫记录添加",notes = "呼叫记录添加")
    @Transactional
    public ResponseEntity<String> add(HttpServletRequest request, @ApiIgnore @CurrentUser SessionModel sessionModel) {
        final String uuid = request.getParameter("uuid");
        log.info("号码呼叫详情添加,uuid：" + uuid);
        TaskCustomer oldCdrObj = this.taskCustomerRepository.findById(uuid).orElse(null);
        log.info("号码呼叫详情添加,任务客户日志关系表为：" + oldCdrObj);
        try {
            final String cdrStr = request.getParameter("cdr");
            log.info("呼叫详情cdr:{}", cdrStr);
            JSONObject jsonObject = JSONObject.parseObject(cdrStr);
            JSONObject cdrVariable = (JSONObject) jsonObject.get("variables");
            //获取号码与任务信息(base64位串)
            String robotB64 = cdrVariable.get("robot").toString();
            String robotJson = Base64Utils.decode(robotB64);
            log.info("任务信息：task{}", robotJson);
            VariablesApiRq cdrObj = JSONObject.parseObject(cdrVariable.toString(), VariablesApiRq.class);
            log.info("日志信息:VariablesApiRq{} ", cdrObj);
            Robot robot = JSONObject.parseObject(robotJson, Robot.class);
            log.info("机器人信息：robot{}", robot);
            if (Objects.isNull(oldCdrObj)) {
                oldCdrObj = new TaskCustomer();
                String customerB64 = cdrVariable.get("customer").toString();
                String customerJson = Base64Utils.decode(customerB64);
                log.info("任务信息：customerJson{}", customerJson);
                Customer customer = JSONObject.parseObject(customerJson, Customer.class);
                log.info("任务信息：customer{}", customer);
                oldCdrObj.setPhone(customer.getPhone());
                oldCdrObj.setVariable(customer.getVariable());
                oldCdrObj.setName(customer.getName());
                oldCdrObj.setSex(Sex.valueOf(customer.getSex()));
                if (StringUtils.isNotEmpty(customer.getCompanyId())) {
                    Company company = companyRepository.findById(customer.getCompanyId()).orElse(new Company());
                    oldCdrObj.setCompany(company);
                } else {
                    log.info("号码呼叫详情添加,uuid：" + uuid + ",没有对应的企业信息");
                }
                String sceneB64 = cdrVariable.get("scene").toString();
                String sceneJson = Base64Utils.decode(sceneB64);
                log.info("任务信息：scene{}", sceneJson);
                Scene scene = JSONObject.parseObject(sceneJson, Scene.class);
                Optional<SceneInfo> optional = sceneInfoRepository.findById(scene.getId());
                if (optional.isPresent()) {
                    oldCdrObj.setScene(optional.get());
                } else {
                    log.info("号码呼叫详情添加,uuid：" + uuid + ",没有对应的场景信息");
                }
                oldCdrObj.setCreateTime(new Date());
                oldCdrObj.setId(uuid);
            }

            Optional<RobotInfo> robotInfo = robotService.findById(robot.getId());
            if (robotInfo.isPresent()) {
                oldCdrObj.setRobotInfo(robotInfo.get());
            } else {
                oldCdrObj.setRobotInfo(null);
            }

            log.info("号码{}保存呼叫详情：IP{}", oldCdrObj.getPhone(), request.getRemoteAddr());
            oldCdrObj.setStartTime(cdrObj.getStart_stamp());
            oldCdrObj.setAnswerTime(cdrObj.getAnswer_stamp());
            oldCdrObj.setHangupTime(cdrObj.getEnd_stamp());
            oldCdrObj.setEndTime(cdrObj.getEnd_stamp());
            oldCdrObj.setDuration(cdrObj.getDuration());
            oldCdrObj.setBillTime(cdrObj.getBillsec());
            if (Objects.nonNull(cdrObj.getBridge_stamp())) {
                oldCdrObj.setBridgeTime(cdrObj.getBridge_stamp());
                Integer botDuration = Math.toIntExact((cdrObj.getBridge_stamp().getTime() - cdrObj.getAnswer_stamp().getTime()) / 1000);
                oldCdrObj.setBotDuration(botDuration);
                Integer seatsDuration = Math.toIntExact((cdrObj.getEnd_stamp().getTime() - cdrObj.getBridge_stamp().getTime()) / 1000);
                oldCdrObj.setSeatsDuration(seatsDuration);
            } else {
                oldCdrObj.setBridgeTime(cdrObj.getEnd_stamp());
                oldCdrObj.setBotDuration(0);
                oldCdrObj.setSeatsDuration(0);
            }
            log.info("保存日志信息:TaskCustomer{} ", oldCdrObj);
            this.taskCustomerRepository.save(oldCdrObj);
            log.info("号码{}保存详情成功", oldCdrObj.getPhone());
            return ResponseEntity.ok().body("ok");
        } catch (Exception e) {
            log.info("号码{}保存呼叫详情失败,原因为:{}", oldCdrObj.getPhone(), e.getMessage());
            e.printStackTrace();
            return ResponseEntity.status(500).body(e.getMessage());
        }
    }

    @PatchMapping("/update")
    @ApiOperation(value = "更新呼叫记录",notes = "更新呼叫记录")
    @Transactional
    public ResponseEntity<String> update(@RequestBody CallDetailRecord cdr, HttpServletResponse response, @ApiIgnore @CurrentUser SessionModel sessionModel){
        TaskCustomer oldCDR = this.taskCustomerRepository.getOne(cdr.getUuid());
        log.info("号码{}更新参数为：{}", oldCDR.getPhone(), cdr);
        if(oldCDR!=null){
            try{
                log.info("号码{}更新呼叫记录",oldCDR.getPhone());
                //因为态度类型为枚举，无法与数据库匹配，所以无法直接copy
                if(StringUtils.isNotEmpty(cdr.getStatus()))
                    oldCDR.setStatus(TaskStatus.valueOf(cdr.getStatus()));
                if (StringUtils.isNotEmpty(cdr.getAttitude())) {
                    Company cop = commonService.getCompany(sessionModel);
                    BooleanBuilder builder = new BooleanBuilder();
                    if (Objects.nonNull(cop)) {
                        builder.and(QCategoryLabel.categoryLabel.companies.contains(cop));
                    } else {
                        builder.and(QCategoryLabel.categoryLabel.source.eq(SourceType.SAFEMANAGER));
                    }
                    builder.and(QCategoryLabel.categoryLabel.code.eq(cdr.getAttitude()));
                    Optional<CategoryLabel> optional = categoryLabelRepository.findOne(builder);
                    if (optional.isPresent()) {
                        CategoryLabel categoryLabel = optional.get();
                        oldCDR.setAttitude(categoryLabel);
                        log.info("号码{}状态更新为{}", oldCDR.getPhone(), categoryLabel);
                    } else {
                        log.info("{}没有在账号{}找到对应信息", cdr.getAttitude(), sessionModel.getUserName());
                        return ResponseEntity.status(500).body("更新失败");
                    }
                }
                if (StringUtils.isNotEmpty(cdr.getCallContent())) {
                    oldCDR.setDialogContent(this.uploadFileRepository.getOne(cdr.getCallContent()));
                }
                if (StringUtils.isNotEmpty(cdr.getCallRecord())) { //录音文件路径
                    File file = new File(cdr.getCallRecord());
                    InputStream inputStream = new FileInputStream(file);
                    MultipartFile multipartFile = new MockMultipartFile(file.getName(), inputStream);
                    UploadFile uploadFile = uploadFileService.fileUpload(multipartFile.getInputStream(), file.getName());
                    oldCDR.setDialogRecord(uploadFile);
                }
                this.taskCustomerRepository.save(oldCDR);
                log.info("号码{}更新呼叫成功",oldCDR.getPhone());
                return ResponseEntity.ok().body("ok");
            }catch (Exception e){
                log.info("号码{}更新呼叫记录失败，原因：{}",oldCDR.getPhone(), e.getMessage());
                e.printStackTrace();
                return ResponseEntity.status(500).body(e.getMessage());
            }
        }
        return ResponseEntity.status(500).body(String.format("未找到对应得id为：得记录。",cdr.getUuid()));
    }

    @GetMapping("/fetchContext")
    @ApiOperation(value = "获取对话内容",notes = "获取对话内容")
    public ResponseEntity<String> fetchContext(@RequestParam(value = "fileName",required = false) String fileName,
            @RequestParam(value = "fileId",required = false) String fileId) throws  Exception{

        if(StringUtils.isNotEmpty(fileId))
            return ResponseEntity.ok().body(FileUtil.readFile(uploadFileService.findOneFileById(fileId)));
        else if(StringUtils.isNotEmpty(fileName))
            return ResponseEntity.ok().body(FileUtil.readFile(uploadFileService.findOneFileByName(fileName)));

        return ResponseEntity.ok().body("");
    }

    @GetMapping("fetchPage")
    @ApiOperation(value = "查询日志信息", notes = "查询日志信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query", value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query", value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query",
                    value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<DialLogResponse>> fetchPage(Pageable pageable,
                                                           DialLogRequest request,
                                                           @ApiIgnore @CurrentUser SessionModel session) {

        Page<DialLogResponse> page = dialLogService.fetchPage(pageable, request, session);
        return ResponseEntity.ok().body(page);
    }

    @GetMapping("fetchPageByTaskId")
    @ApiOperation(value = "查询日志信息", notes = "查询日志信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query", value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query", value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query",
                    value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<TaskLogResponse>> fetchPageByTaskId(Pageable pageable,
                                                                   @RequestParam("taskId") String taskId,
                                                                   @RequestParam(value = "name", required = false) String name,
                                                                   @RequestParam(value = "phone", required = false) String phone,
                                                                   @RequestParam(value = "status", required = false) TaskStatus status) {
        Page<TaskLogResponse> page = dialLogService.fetchPageByTaskId(pageable, taskId, name, phone, status);
        return ResponseEntity.ok().body(page);
    }


    @GetMapping("fetch")
    @ApiOperation(value = "查询日志信息", notes = "查询日志信息")
    public ResponseEntity<List<DialLogResponse>> fetch(DialLogRequest request,
                                                       @ApiIgnore @CurrentUser SessionModel session) {
        List<DialLogResponse> list = dialLogService.fetch(request, session);
        return ResponseEntity.ok().body(Lists.newArrayList(list));
    }

    @GetMapping("/downloadLog")
    @ApiOperation(value = "下载电话拨打日志", notes = "下载电话拨打日志")
    public ResponseEntity<Void> downloadLog(HttpServletResponse response,
                                            DialLogRequest request,
                                            @ApiIgnore @CurrentUser SessionModel session) throws Exception {
        dialLogService.downloadLog(response, request, session);
        return ResponseEntity.ok().build();
    }
}
